From d58f907f31ec9b7ece8e8f524930820cc38537a3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Wed, 23 Aug 2017 20:22:24 +0200 Subject: [PATCH] babl-icc: implement reading and writing of LUTs for TRC --- babl/babl-classes.h | 2 +- babl/babl-icc.c | 146 ++++++++++++++++++++++++++++++-------------- babl/babl-trc.c | 23 ++++++- babl/babl-trc.h | 2 +- 4 files changed, 124 insertions(+), 49 deletions(-) diff --git a/babl/babl-classes.h b/babl/babl-classes.h index eb05add..ea8d6b5 100644 --- a/babl/babl-classes.h +++ b/babl/babl-classes.h @@ -80,7 +80,7 @@ typedef union _Babl BablType type; BablSampling sampling; BablSpace space; - BablSpace trc; + BablTRC trc; BablComponent component; BablModel model; BablFormat format; diff --git a/babl/babl-icc.c b/babl/babl-icc.c index 69f0df0..8a94336 100644 --- a/babl/babl-icc.c +++ b/babl/babl-icc.c @@ -44,8 +44,6 @@ ICC *icc_state_new (char *data, int length, int tags) return ret; } - - #define ICC_HEADER_LEN 128 #define TAG_COUNT_OFF ICC_HEADER_LEN @@ -137,6 +135,12 @@ static s15f16_t read_s15f16_ (ICC *state, int offset) return ret; } +static void write_u8f8_ (ICC *state, int offset, u8f8_t val) +{ + icc_write (u8, offset, val.integer), + icc_write (u8, offset + 1, val.fraction); +} + static void write_s15f16_ (ICC *state, int offset, s15f16_t val) { icc_write (s16, offset, val.integer), @@ -151,6 +155,14 @@ static s15f16_t d_to_s15f16 (double value) return ret; } +static u8f8_t d_to_u8f8 (double value) +{ + u8f8_t ret; + ret.integer = floor (value); + ret.fraction = fmod(value, 1.0) * 255.999; + return ret; +} + static double s15f16_to_d (s15f16_t fix) { return fix.integer + fix.fraction / 65535.0; @@ -166,6 +178,12 @@ static void write_s15f16 (ICC *state, int offset, double value) write_s15f16_ (state, offset, d_to_s15f16 (value)); } +static void write_u8f8 (ICC *state, int offset, double value) +{ + write_u8f8_ (state, offset, d_to_u8f8 (value)); +} + + static double read_s15f16 (ICC *state, int offset) { return s15f16_to_d (read_s15f16_ (state, offset)); @@ -298,16 +316,17 @@ static const Babl *babl_trc_from_icc (ICC *state, int offset, } else { - return babl_trc_gamma (10.0); - // XXX: todo implement a curve trc babl type - // as well as detect sRGB curve from LUTs + const Babl *ret; + float *lut = babl_malloc (sizeof (float) * count); for (i = 0; i < count && i < 10; i ++) { - fprintf (stdout, "%i=%i ", i, icc_read (u16, offset + 12 + i * 2)); - if (i % 7 == 0) - fprintf (stdout, "\n"); + lut[i] = icc_read (u16, offset + 12 + i * 2) / 65535.0; } + + ret = babl_trc_lut (NULL, count, lut); + babl_free (lut); + return ret; } } } @@ -331,36 +350,57 @@ static void icc_duplicate_tag(ICC *state, const char *tag) icc_write (u32, 128 + 4 + 4 * state->headpos++, state->psize); } +void write_trc (ICC *state, const char *name, const BablTRC *trc); +void write_trc (ICC *state, const char *name, const BablTRC *trc) +{ +switch (trc->type) +{ + case BABL_TRC_LINEAR: + icc_allocate_tag (state, name, 13); + icc_write (sign, state->o, "curv"); + icc_write (u32, state->o + 4, 0); + icc_write (u32, state->o + 8, 0); + break; + case BABL_TRC_GAMMA: + icc_allocate_tag (state, name, 14); + icc_write (sign, state->o, "curv"); + icc_write (u32, state->o + 4, 0); + icc_write (u32, state->o + 8, 1); + icc_write (u8f8, state->o + 12, trc->gamma); + break; + case BABL_TRC_LUT: + icc_allocate_tag (state, name, 13 + trc->lut_size * 2); + icc_write (sign, state->o, "curv"); + icc_write (u32, state->o + 4, 0); + icc_write (u32, state->o + 8, trc->lut_size); + { + int j; + for (j = 0; j < trc->lut_size; j ++) + icc_write (u16, state->o + 12 + j * 2, (int)(trc->lut[j]*65535.5f)); + } + break; + default: + icc_allocate_tag (state, "rTRC", 14); + icc_write (sign, state->o, "curv"); + icc_write (u32, state->o + 4, 0); + icc_write (u32, state->o + 8, 1); + icc_write (u16, state->o + 12, 0); + break; +} +} + +static void symmetry_test (ICC *state); + const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length) { const BablSpace *space = &babl->space; - static char icc[8192]; - int length=4095; + static char icc[65536]; + int length=65535; ICC *state = icc_state_new (icc, length, 10); icc[length]=0; -#if 0 - icc_write (s8, 8,-2); - assert (icc_read (s8, 8) == -2); - icc_write (s8, 8, 3); // ICC verison - assert (icc_read (s8, 8) == 3); - - icc_write (u8, 8, 2); // ICC verison - assert (icc_read (u8, 8) == 2); - - icc_write (u16, 8, 3); // ICC verison - assert (icc_read (u16, 8) == 3); - - icc_write (s16, 8, -3); // ICC verison - assert (icc_read (s16, 8) == -3); - - icc_write (s16, 8, 9); // ICC verison - assert (icc_read (s16, 8) == 9); - - icc_write (u32, 8, 4); // ICC verison - assert (icc_read (u32, 8) == 4); -#endif + symmetry_test (state); icc_write (sign, 4, "babl"); // ICC verison icc_write (u8, 8, 2); // ICC verison @@ -400,7 +440,7 @@ const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length) icc_allocate_tag (state, "wtpt", 20); icc_write (sign, state->o, "XYZ "); icc_write (u32, state->o + 4, 0); - icc_write (s15f16, state->o + 8, space->whitepoint[0]); + icc_write (s15f16, state->o + 8, space->whitepoint[0]); icc_write (s15f16, state->o + 12, space->whitepoint[1]); icc_write (s15f16, state->o + 16, space->whitepoint[2]); @@ -425,11 +465,7 @@ const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length) icc_write (s15f16, state->o + 12, space->RGBtoXYZ[5]); icc_write (s15f16, state->o + 16, space->RGBtoXYZ[8]); - icc_allocate_tag (state, "rTRC", 14); - icc_write (sign, state->o, "curv"); - icc_write (u32, state->o + 4, 0); - icc_write (u32, state->o + 8, 1); - icc_write (u16, state->o + 12, 334); + write_trc (state, "rTRC", &space->trc[0]->trc); if (space->trc[0] == space->trc[1] && space->trc[0] == space->trc[2]) @@ -439,14 +475,9 @@ const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length) } else { - icc_allocate_tag (state, "gTRC", 14); - icc_write (sign, state->o, "curv"); - icc_write (u32, state->o + 4, 0); - icc_write (u32, state->o + 8, 1); /* forcing a linear curve */ - icc_allocate_tag (state, "bTRC", 14); - icc_write (sign, state->o, "curv"); - icc_write (u32, state->o + 4, 0); - icc_write (u32, state->o + 8, 1); /* forcing a linear curve */ + fprintf (stderr, "!!!!!!!!\n"); + write_trc (state, "gTRC", &space->trc[1]->trc); + write_trc (state, "bTRC", &space->trc[2]->trc); } { @@ -536,7 +567,6 @@ babl_space_rgb_icc (const char *icc, } } - if (!*error && (!trc_red || !trc_green || !trc_blue)) { *error = "missing TRCs"; @@ -637,3 +667,27 @@ babl_space_rgb_icc (const char *icc, babl_free (state); return NULL; } + +static void symmetry_test (ICC *state) +{ + icc_write (s8, 8,-2); + assert (icc_read (s8, 8) == -2); + icc_write (s8, 8, 3); // ICC verison + assert (icc_read (s8, 8) == 3); + + icc_write (u8, 8, 2); // ICC verison + assert (icc_read (u8, 8) == 2); + + icc_write (u16, 8, 3); // ICC verison + assert (icc_read (u16, 8) == 3); + + icc_write (s16, 8, -3); // ICC verison + assert (icc_read (s16, 8) == -3); + + icc_write (s16, 8, 9); // ICC verison + assert (icc_read (s16, 8) == 9); + + icc_write (u32, 8, 4); // ICC verison + assert (icc_read (u32, 8) == 4); +} + diff --git a/babl/babl-trc.c b/babl/babl-trc.c index 5719e03..e2f9838 100644 --- a/babl/babl-trc.c +++ b/babl/babl-trc.c @@ -51,6 +51,19 @@ babl_trc_new (const char *name, trc.type = type; trc.gamma = gamma; + if (n_lut ) + { + for (i = 0; trc_db[i].instance.class_type; i++) + { + if ( trc_db[i].lut_size == n_lut && + (memcmp (trc_db[i].lut, lut, sizeof (float) * n_lut)==0) + ) + { + return (void*)&trc_db[i]; + } + } + } + else for (i = 0; trc_db[i].instance.class_type; i++) { int offset = ((char*)&trc_db[i].type) - (char*)(&trc_db[i]); @@ -70,9 +83,18 @@ babl_trc_new (const char *name, trc_db[i].instance.name = trc_db[i].name; if (name) sprintf (trc_db[i].name, "%s", name); + else if (n_lut) + sprintf (trc_db[i].name, "lut-trc"); else sprintf (trc_db[i].name, "trc-%i-%f", type, gamma); + if (n_lut) + { + trc_db[i].lut_size = n_lut; + trc_db[i].lut = babl_calloc (sizeof (float), n_lut); + memcpy (trc_db[i].lut, lut, sizeof (float) * n_lut); + } + return (Babl*)&trc_db[i]; } @@ -106,7 +128,6 @@ babl_trc_gamma (double gamma) return babl_trc_new (name, BABL_TRC_GAMMA, gamma, 0, NULL); } - void babl_trc_class_init (void) { diff --git a/babl/babl-trc.h b/babl/babl-trc.h index c762810..abcf2e2 100644 --- a/babl/babl-trc.h +++ b/babl/babl-trc.h @@ -34,10 +34,10 @@ typedef struct { BablInstance instance; BablTRCType type; + int lut_size; double gamma; char name[128]; float *lut; - int lut_size; } BablTRC; static inline double babl_trc_lut_from_linear (const Babl *trc_, double value) -- 2.30.2